<template>
    <div ref="parent" class="f-scroll-wrapper" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave" @wheel="onWheel">
        <div ref="child" class="f-scroll" :style="{transform:`translateY(${this.contentY}px)`}">
            <slot></slot>
        </div>
        <div class="f-scroll-track" v-show="scrollBarVisible">
            <div class="f-scroll-bar" ref="bar" @mousedown="onMouseDownScrollBar" @selectstart="onSelectStartScrollBar">
                <div class="f-scroll-bar-inner"></div>
            </div>
        </div>
    </div>
</template>

<script>
  export default {
    name: "FScroll"
    ,data(){
      return {
        scrollBarVisible:false
        ,isScrolling:false
        ,startPosition:undefined
        ,endPosition:undefined
        ,scrollBarY:0
        ,contentY:0
        ,barHeight:undefined
        ,parentHeight:undefined
        ,childHeight:undefined
      }
    }
    ,computed:{
      maxScrollHeight(){
        return this.parentHeight - this.barHeight;
      }
    }
    ,beforeDestroy() {
      //移除 document 的事件监听
    }
    ,mounted() {
      /*let test = document.querySelector('#test');
      let startPosition;
      let endPosition;
      let isMoving = false;
      let top
        ,left;
      let translateX = 0;
      let translateY = 0;
      test.addEventListener('mousedown', (e) => {
        isMoving = true;
        let {screenX, screenY} = e;
        startPosition = {x: screenX, y: screenY};
        // top = window.getComputedStyle(test).top;
        // left = window.getComputedStyle(test).left;
      });
      test.addEventListener('selectstart',(e)=>{e.preventDefault()});
      document.addEventListener('mousemove', (e) => {
        if(!isMoving) return;
        let {screenX, screenY} = e;
        endPosition = {x: screenX, y: screenY};
        let delta = {x: endPosition.x - startPosition.x, y: endPosition.y - startPosition.y};
        // let {top, left} = window.getComputedStyle(test);
        // test.style.top = parseInt(top) + delta.y + 'px';
        // test.style.left = parseInt(left) + delta.x + 'px';
        translateX = parseInt(this.translateX) + delta.x;
        translateY = parseInt(this.translateY) + delta.y;
        startPosition = endPosition;
        test.style.transform = `translate(0px,${translateY}px)`;
      });
      document.addEventListener('mouseup', (e) => {
        isMoving = false;
      });*/
      this.listenToDocument();
      this.parentHeight = this.$refs.child.getBoundingClientRect().height;
      this.childHeight = this.$refs.parent.getBoundingClientRect().height;

      this.updateScrollBar();
    }
    /*,watch:{
      scrollBarY(newValue){
        console.log(this.contentY);
        this.contentY = -(this.childHeight * newValue / this.parentHeight);
      }
    }*/
    ,methods:{
      listenToDocument(){
        document.addEventListener('mousemove', (e) => {
          this.onMouseMoveScrollBar(e);
        });
        document.addEventListener('mouseup', (e) => {
          this.onMouseUpScrollBar(e);
        });
      },
      calcContentYFromDeltaY(deltaY){
        let contentY;
        if(deltaY > 20){
          contentY -= 20 * 3;
        }else if(deltaY<-20){
          contentY -= -20 * 3;
        }else{
          contentY -= deltaY * 3;
        }
        return contentY;
      },
      onWheel(e){
        this.updateContentY(e);
        // child.style.transform = `translateY${this.contentY}px`;
        this.updateScrollBar();
      },
      updateContentY(e){
        let maxHeight = this.calcContentYMax();
        this.contentY = this.calcContentYFromDeltaY();

        //对contentY加限制
        if(this.contentY>0){
          this.contentY = 0;
        }else if(this.contentY<-maxHeight){
          this.contentY = -maxHeight;
        }else{
          e.preventDefault();
        }
      },
      calcContentYMax(){
        let {borderTopWidth,borderBottomWidth,paddingTop,paddingBottom} = window.getComputedStyle(this.$refs.parent);
        borderTopWidth = parseInt(borderTopWidth);
        borderBottomWidth = parseInt(borderBottomWidth);
        paddingTop = parseInt(paddingTop);
        paddingBottom = parseInt(paddingBottom);
        let maxHeight = this.childHeight - this.parentHeight + (borderTopWidth + borderBottomWidth + paddingTop + paddingBottom);
        return maxHeight;
      },
      updateScrollBar(){
        let parentHeight = this.parentHeight;
        let childHeight = this.childHeight;
        this.barHeight = parentHeight * parentHeight / childHeight;
        this.$refs.bar.style.height = this.barHeight + 'px';
        this.scrollBarY = -parentHeight + this.contentY / childHeight;
        this.$refs.bar.style.transform = `translateY(${this.scrollBarY}px)`;
      }
      ,onMouseEnter(){
        this.scrollBarVisible = true;
      }
      ,onMouseLeave(){
        this.scrollBarVisible = false;
        // this.isScrolling = false;
      }
      ,onMouseDownScrollBar(e){
        this.isScrolling = true;
        let {screenX, screenY} = e;
        this.startPosition = {x: screenX, y: screenY};
      }
      ,onMouseMoveScrollBar(e){
        if(!this.isScrolling) return;
        this.endPosition = {x: e.screenX, y: e.screenY};
        let delta = {x: this.endPosition.x - this.startPosition.x, y: this.endPosition.y - this.startPosition.y};
        // this.translateX = parseInt(this.translateX) + delta.x;
        //更新 scrollBarY
        this.scrollBarY = this.calcScrollBayY(delta);
        this.contentY = -(this.childHeight * this.scrollBarY / this.parentHeight);
        this.startPosition = this.endPosition;
        this.$refs.bar.style.transform = `translate(0px,${this.scrollBarY}px)`;
      }
      ,calcScrollBayY(delta){
        let newValue = parseInt(this.scrollBarY) + delta.y;
        if(newValue<0){
          newValue = 0;
        }else if(newValue>this.maxScrollHeight){
          newValue = this.maxScrollHeight;
        }
        return newValue;
      }
      ,onMouseUpScrollBar(){
        this.isScrolling = false;
      }
      ,onSelectStartScrollBar(e){
        e.preventDefault();
      }
    }
  }
</script>

<style lang="scss">
    .f-scroll{
        border:5px solid green;
        transition:transform 0.05s ease;
        &-wrapper{
            border:5px solid red;
            overflow: hidden;
            position:relative;
        }
        &-track{
            position:absolute;
            top:0;
            right:0;
            width:13px;
            height:100%;
            border:1px solid #e8e7e8;
            background:#fafafa;
            border-radius:4px;
            opacity: .9;
        }
        &-bar{
            position:absolute;
            left:50%;
            top:-1px;
            height:40px;
            width:8px;
            margin-left:-4px;
            padding:4px 0;
            &-inner{
                height:100%;
                border-radius:4px;
                background:#c2c2c2;
                &:hover{
                    background:#7d7d7d;
                }
            }
        }
    }
</style>
